#!/bin/bash
#
# addpage
#
# Page addition helper for the Dragora GNU/Linux-Libre website
# (https://www.dragora.org)
#
#
# Copyright (C) 2021 Michael Siegel
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


#### INCLUDES ####

. include/constants || exit 1
. include/subroutines || exit 1


#### CONSTANTS ####


#### GLOBAL PARAMETERS ####

pg_basedir=
pg_dir=
pg_prefixdir=
pg_title=

in_nav=
nav_slot=
nav_direction=

  
#### FUNCTIONS ####

## Retrievers

_show_navtree() {

  local -r index_start=0
  local indent=
  local item=
  local line_mark=
  
  local prefix="${1}/"
  local -r index_end="$(("${#navtree[@]}" - 1))"
  local -r index_width="${#index_end}"

  _get_tree_flow "${navtree[@]}"  # _mk_tree_item_indent needs this

  local i=
  for ((i="$index_start"; i<="$index_end"; ++i))
  do
    if [[ "$i" -eq 0 ]]  # Beware that this requires the start page to always
                         # be the first in the site navigation.
    then
      item='[home page]'
    else
      item="${navtree[i]}"
    fi

    indent="$(_mk_tree_item_indent "$item" "$i")"
    if [[ "$item" = "$prefix" ]]
    then
      line_mark='* '
    else
      line_mark='  '
    fi
    item="${item%/}"
    printf "%s%${index_width}s  %s%s%s\n" "$line_mark" "$i" "$indent" \
      "${item##*/}"
  done
  unset i
}

## User queries and input parsers

_prompt_basedir() {

  local input=

  while true
  do
    if [[ -z "$input" ]]
    then
      printf '%s\n' 'Please provide a directory name for the new page to add.'
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    fi

    read -rp "$PROMPT" input

    if [[ -z "$input" ]]
    then
      continue 
    elif [[ "$input" = "$HELP_COMMAND" ]]
    then
      _show_help "$FUNCNAME"
    elif [[ ! "$input" =~ ^[abcdefghijklmnopqrstuvwxyz0123456789_]+$ ]]
    then
      _perr "invalid directory name -- '$input'"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    else
      break
    fi
  done

  pg_basedir="$input"
}

_prompt_title() {

  local input=

  while true
  do
    if [[ -z "$input" ]]
    then
      printf '%s\n' 'Please provide a title for the new page.'
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    fi

    read -rp "$PROMPT" input

    if [[ -z "$input" ]]
    then
      continue
    elif [[ "$input" = "$HELP_COMMAND" ]]
    then
      _show_help "$FUNCNAME"
    else
      break
    fi
  done

  # Currently, $pg_title may contain anything but a newline.
  # Apply further restrictions: The only whitespace character allowed shall be
  # space.

  pg_title="$input"
}

_prompt_prefixdir() {

  local input=

  while true
  do
    if [[ -z "$input" ]]
    then
      printf '%s\n' 'Please select where you want the new page to be placed:'
      _show_pagetree -add
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    fi

    read -rp "$PROMPT" input

    if [[ -z "$input" ]]
    then
      continue
    elif [[ "$input" = "$HELP_COMMAND" ]]
    then
      _show_help "$FUNCNAME"
    elif [[ ! "$input" =~ ^[0123456789]+$ ]]
    then
      _perr "invalid selection -- '$input'"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    else
      if [[ ! "$input" -lt "${#pagetree[@]}" ]]
      then
         _perr "invalid selection -- '$input'"
         printf '%s\n' "$HELP_TIP_INTERACTIVE"
      else
        break
      fi
    fi
  done

  [[ "$input" -ne 0 ]] && pg_prefixdir="${pagetree["$input"]%/}"
}

_prompt_putnav() {

  local input=

  while true
  do
    if [[ -z "$input" ]]
    then
      printf '%s\n' \
        'Do you want the new page to appear in the site navigation? [y/n]'
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    fi
    
    read -rp "$PROMPT" input

    if [[ -z "$input" ]]
    then
      continue
    elif [[ "$input" = "$HELP_COMMAND" ]]
    then
      _show_help "$FUNCNAME"
    elif [[ ! "$input" =~ ^y|n$ ]]
    then
      _perr "invalid input -- '$input'"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    else
      break
    fi
  done

  case "$input" in
    y)
      in_nav=1
    ;;
    n)
      in_nav=0
    ;;
  esac
}

_prompt_navplace() {

  local input=

  while true
  do
    if [[ -z "$input" ]]
    then
      printf '%s\n' \
        'Where in the site navigation do you want the new page to appear?'
      _show_navtree "$pg_prefixdir"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    fi

    read -rp "$PROMPT" input

    if [[ -z "$input" ]]
    then
      continue
    elif [[ "$input" = "$HELP_COMMAND" ]]
    then
      _show_help "$FUNCNAME"
    elif [[ "${#input}" -lt 2 || ! "$input" =~ ^b|a[0-9]+$ ]]
    then
      _perr "invalid selection -- '$input'"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    elif [[ ! "${input:1}" -lt "${#navtree[@]}" ]]
    then
      _perr "invalid selection -- '$input'"
      printf '%s\n' "$HELP_TIP_INTERACTIVE"
    else
      break
    fi 
  done

  nav_slot="${input:1}"  # just the number
  nav_direction="${input:0:1}"  # just the letter
}

_set_pagedir() {

  if [[ -z "$pg_prefixdir" ]]
  then
    pg_dir="$pg_basedir"
  else
    pg_dir="$pg_prefixdir/$pg_basedir"
  fi
}

## Checks

_probe_pagedir() {

  if [[ -e "$PAGES_DIR_MASTER/$pg_dir" ]]
  then
    _perr "Page directory '$pg_dir' already exists."
    return 1
  fi
}

## Actions

_add_page() {

  local pg_dir_full=
  local pg_file="$SOURCE_PAGE_FILENAME"

  local lang_dir=
  for lang_dir in $(_get_lang_dirs)
  do
    pg_dir_full="$PAGES_DIR/$lang_dir/$pg_dir"
    mkdir -p -- "$pg_dir_full" || return 1
    printf '%s\n\n%s' \
      "<!--PAGETITLE:${pg_title}-->" "<h2>$pg_title</h2>" \
      > "$pg_dir_full/$pg_file" || return 1
    printf '%s\n' "Added page '$pg_dir_full/$pg_file'."
    unset pg_dir_full
  done
  unset lang_dir
}

_add_page_nav() {

  local nav_slot_lnum=0
  local prefix=

  [[ -z "$nav_direction" ]] && nav_direction=a

  if [[ -z "$nav_slot" ]]
  then
    prefix="${pg_prefixdir}/"
  else
    prefix="${navtree[$nav_slot]}"
  fi

  local line=
  # Find the line number of "$prefix" in $NAVTREE_FILE
  while read -r line
  do
    [[ "$line" = "$prefix" ]] && break
    ((++nav_slot_lnum))
  done < "$NAVTREE_FILE"
  unset line

  cp -a -- "$NAVTREE_FILE" "${NAVTREE_FILE}.old"

  case "$nav_direction" in
    b)
      sed -- "$nav_slot_lnum a\\$pg_dir/" "$NAVTREE_FILE" \
        > "$TMP_DIR/navtree"
    ;;
    a)
      ((++nav_slot_lnum))
      sed -- "$nav_slot_lnum a\\$pg_dir/" "$NAVTREE_FILE" \
        > "$TMP_DIR/navtree"
    ;;
  esac

  mv -- "$TMP_DIR/navtree" "$NAVTREE_FILE"
  printf '%s\n' "Added '$pg_dir' to site navigation."
}

_show_help() {

  case "$1" in
    _prompt_basedir)
cat <<'EOF'
Page directory names may only contain lowercase ASCII letters (a-z), ASCII
digits (0-9), and the underscore (_).
EOF
    ;;
    _prompt_prefixdir)
cat <<'EOF'
Simply enter the number corresponding to the path into which you want the new
page to be placed, or `0` to create a new top-level page.
EOF
    ;;
#    _prompt_putnav)
#    :
#    ;;
    _prompt_navplace)
cat <<'EOF'
Please select the desired slot number and indicate whether the new page shall
be inserted before or after the chosen slot, by putting either `b` (before) or
`a` (after) infront of the slot number -- e.g., `a2`, to insert after the
second slot.
EOF
    ;;
    global)
cat <<'EOF'
Add a page interactively

Usage:
    addpage

Options:
    --help
        Show this help text and exit
EOF
    ;;
    *)
      printf '%s\n' "Sorry, no help text available."
    ;;
  esac
}


#### MAIN ####

if [[ "$1" = '--help' ]]
then
  _show_help global
  exit
fi

## Environment checks

_env_checks || _abort

## Action

_get_pagetree
_get_navtree

_prompt_prefixdir
while true
do
  _prompt_basedir
  _set_pagedir
  _probe_pagedir && break
done
_prompt_title
_prompt_putnav

if [[ "$in_nav" -eq 1 ]] && \
  [[ "$(find "${PAGES_DIR_MASTER}/$pg_prefixdir" -type d | wc -l)" -gt 1 ]]
then
  _prompt_navplace
fi

_add_page || _abort
[[ "$in_nav" -eq 1 ]] && _add_page_nav
